package JUC.comsumer10Producer2;


import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @className: RLockConditionConPro
 * @Description:
 * @Author: wangyifei
 * @Date: 2022/9/7 15:38
 */
public class RLockConditionConPro {
    private Queue<Integer> queue = new LinkedList<>();
    private ReentrantLock lock = new ReentrantLock();
    private Condition consumerCondition = lock.newCondition();
    private Condition producerCondition = lock.newCondition();
    public static volatile boolean running = true ;

    public void consume(){
        lock.lock();
        try{
            while(queue.isEmpty()){
                consumerCondition.await();
            }
            Integer poll = queue.poll();
            System.out.println(Thread.currentThread().getName() + " consume " + poll);
            producerCondition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void produce(){
        lock.lock();
        try{
            while(queue.size() >= 10){
                producerCondition.await();
            }
            int i = new Random().nextInt(10);
            queue.add(i);
            System.out.println(Thread.currentThread().getName() + " produce " + i);
            consumerCondition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        RLockConditionConPro queue = new RLockConditionConPro();
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
               15
                , 15
                , 1000
                , TimeUnit.SECONDS
                , new ArrayBlockingQueue<>(1000)
        );
        for(int i = 0 ; i < 10 ; i++){
            pool.submit(()->{
                while(RLockConditionConPro.running){
                    queue.produce();
                }
            });
        }
        for(int i = 0 ; i < 5 ; i++){
            pool.submit(()->{
                while(RLockConditionConPro.running){
                    queue.consume();
                }
            });
        }
        Scanner s = new Scanner(System.in);
        String line = null ;
        while(s.hasNextLine()){
            if("stop".equals(s.nextLine())){
                break;
            }
        }
        pool.shutdown();
    }
}
